//
//  StatzLoginPlugin.m
//  Statz
//
//  Created by dmaclach on 6/17/07.
//
// Copyright 2007 Google Inc.
// 
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License.  You may obtain a copy
// of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
// License for the specific language governing permissions and limitations under
// the License.
//


#import "StatzLoginPlugin.h"
#include <Security/Security.h>


@implementation StatzLoginPlugin

- (void)dealloc {
  [tempPassword release];
  [tempUsername release];
  [super dealloc];
}

- (NSString *)password {
  NSString *password = tempPassword;
  NSString *username = [self username];
  if (!password && username) {
    const char* serverName = [[self serverName] UTF8String];
    const char* accountName = [username UTF8String];
    UInt32 length;
    void *passwordData;
    OSStatus status = SecKeychainFindInternetPassword(NULL,
                                                      strlen(serverName),
                                                      serverName,
                                                      0,
                                                      NULL,
                                                      strlen(accountName),
                                                      accountName,
                                                      0,
                                                      "",
                                                      0,
                                                      kSecProtocolTypeHTTP,
                                                      kSecAuthenticationTypeDefault,
                                                      &length,
                                                      &passwordData,
                                                      NULL);
    if (status == noErr) {
      password = [[[NSString alloc] initWithBytes:passwordData 
                                           length:length
                                         encoding:NSUTF8StringEncoding] autorelease];
      SecKeychainItemFreeContent(NULL, passwordData);
    }
  }
  return password;
}

- (void)setUsername:(NSString *)username {
  [tempUsername autorelease];
  tempUsername = [username retain];
}

- (void)setPassword:(NSString *)password {
  [tempPassword autorelease];
  tempPassword = [password retain];
}

- (void)savePreferences {
  if (tempUsername) {
    [[NSUserDefaults standardUserDefaults] setObject:tempUsername 
                                              forKey:[self fullPrefNameForPreferences:@"username"]];
    [tempUsername release];
    tempUsername = nil;
  }
  
  const char* serverName = [[self serverName] UTF8String];
  const char* accountName = [[self username] UTF8String];
  if (tempPassword) {
    const char* tempPasswordUTF8 = [tempPassword UTF8String];
    SecKeychainItemRef passwordSecItem;
    OSStatus status = SecKeychainFindInternetPassword(NULL,
                                                      strlen(serverName),
                                                      serverName,
                                                      0,
                                                      NULL,
                                                      strlen(accountName),
                                                      accountName,
                                                      0,
                                                      "",
                                                      0,
                                                      kSecProtocolTypeHTTP,
                                                      kSecAuthenticationTypeDefault,
                                                      NULL,
                                                      NULL,
                                                      &passwordSecItem);
    if (status == noErr) {
      status = SecKeychainItemModifyAttributesAndData(passwordSecItem,
                                                      NULL,
                                                      strlen(tempPasswordUTF8),
                                                      tempPasswordUTF8);
    } else {
      status = SecKeychainAddInternetPassword (NULL,
                                               strlen(serverName),
                                               serverName,
                                               0,
                                               NULL,
                                               strlen(accountName),
                                               accountName,
                                               0,
                                               "",
                                               0,
                                               kSecProtocolTypeHTTP,
                                               kSecAuthenticationTypeDefault,
                                               strlen(tempPasswordUTF8),
                                               tempPasswordUTF8,
                                               NULL);
    }
    [tempPassword release];
    tempPassword = nil;
  }
  [super savePreferences];
}

- (void)cancelPreferences {
  [self setUsername:nil];
  [self setPassword:nil];
  [super cancelPreferences];
}

- (BOOL)shouldPreferencesClose {
  BOOL shouldClose = [super shouldPreferencesClose];
  if (shouldClose) {
    shouldClose = [[self username] length] && [[passwordField stringValue] length];

  }
  return shouldClose;
}

- (BOOL)hasPreferences {
  return YES;
}

- (NSString*)username {
  NSString *username = tempUsername;
  if (!username) {
    NSString *userNamePref = [self fullPrefNameForPreferences:@"username"];
    username = [[NSUserDefaults standardUserDefaults] objectForKey:userNamePref];
    if (!username) {
      username = [self findUserNameForServerName:[self serverName]];
    }
  }
  return username;
}

- (NSString*)findUserNameForServerName:(NSString*)serverName {
  NSString *keychainUsername = nil;
  SecKeychainRef keychainRef = nil;
  OSStatus status = SecKeychainCopyDefault(&keychainRef);
  if (status == noErr) {
    SecKeychainAttribute attr = { 
      kSecServerItemAttr, 
      strlen([serverName UTF8String]), 
      (char*)[serverName UTF8String] 
    };
    SecKeychainAttributeList attrList = {1, &attr};
    SecKeychainSearchRef searchRef = nil;
    status = SecKeychainSearchCreateFromAttributes(keychainRef, 
                                                   kSecInternetPasswordItemClass, 
                                                   &attrList, 
                                                   &searchRef);
    if (status == noErr) {
      SecKeychainItemRef item;
      status = SecKeychainSearchCopyNext(searchRef, &item);
      if (status == noErr) {
        UInt32 attrs[] = { kAccountKCItemAttr };
        SecKeychainAttributeInfo info = {1, attrs, NULL};
        SecKeychainAttributeList *returnedAttrList = NULL;
        UInt32 length;
        status = SecKeychainItemCopyAttributesAndData(item, 
                                                      &info, 
                                                      NULL, 
                                                      &returnedAttrList,
                                                      &length, 
                                                      NULL);
        if (status == noErr && returnedAttrList) {
          SecKeychainAttribute *attribute = returnedAttrList->attr;
          if (returnedAttrList->count == 1 && attribute[0].length) {
            keychainUsername = [[[NSString alloc] initWithBytes:attribute[0].data 
                                                         length:attribute[0].length 
                                                       encoding:NSUTF8StringEncoding] autorelease];
          }
          SecKeychainItemFreeAttributesAndData(returnedAttrList, NULL);
        }
        CFRelease(item);
      }
      CFRelease(searchRef);
    }
    CFRelease(keychainRef);
  }
  return keychainUsername;
}


@end
